                         {beginning of STAR.PART2.TEXT}

PROCEDURE move_enterprise;
VAR course : INTEGER;
    x_inc, y_inc, x_pos, y_pos, warp : REAL;

  PROCEDURE handle_damage;
  VAR ch, start_ch : CHAR;
  BEGIN
    FOR ch := min_device TO max_device DO
      IF device[ch].down_time <> 0 THEN
        device[ch].down_time := device[ch].down_time - 1;
    IF random (0, 100) < 6 THEN
      BEGIN
        ch := CHR (random (ORD (min_device), ORD (max_device)));
        WRITELN ('*** Space storm, ', device[ch].name, ' damaged ***');
        device[ch].down_time := random (device[ch].down_time, 5);
      END {of IF}
    ELSE
      IF random (0, 100) < 12 THEN
        BEGIN
          ch := CHR (random (ORD (min_device), ORD (max_device)));
          start_ch := ch;
          REPEAT
            IF ch = max_device THEN
              ch := min_device
            ELSE
              ch := SUCC (ch);
          UNTIL (ch = start_ch) OR (device[ch].down_time <> 0);

          IF device[ch].down_time <> 0 THEN
            BEGIN
              WRITELN ('*** Truce, ', device[ch].name, 
                       ' state of repair improved ***');
              device[ch].down_time := random (0, device[ch].down_time - 1);
            END {of IF device};
        END {of IF random};
  END {of handle_damage};
  
  PROCEDURE move_intra (VAR x_pos, y_pos, x_inc, y_inc : REAL; 
                        course : INTEGER; warp : REAL);
  BEGIN
    x_inc := -COS (radians (course));
    y_inc := SIN (radians (course));
    x_pos := cur_sect.x;
    y_pos := cur_sect.y;
    WHILE (ROUND (x_pos) IN [0..quad_size]) AND
          (ROUND (y_pos) IN [0..quad_size]) AND (warp >= 0.125) DO
      IF quadrant[ROUND (x_pos), ROUND (y_pos)] = s_nothing THEN
        BEGIN
          x_pos := x_pos + x_inc;
          y_pos := y_pos + y_inc;
          warp := warp - 0.125;
        END {of IF}
      ELSE
        warp := 0.0;
  END {of move_intra};

BEGIN {of move_enterprise}
  WRITE ('Course: ');
  READLN (course);
  WRITE ('Warp factor (0-12): ');
  READLN (warp);
  IF (warp < 0.0) OR (warp > 12.0) OR 
     ((warp > 0.2) AND (device[min_device].down_time <> 0)) THEN
    WRITELN ('Can''t move that fast !!')
  ELSE
    BEGIN
      cur_year := cur_year + 1;
      cur_energy := TRUNC (cur_energy - 8 * warp);
      handle_damage;
      quadrant[cur_sect.x, cur_sect.y] := s_nothing;
      move_intra (x_pos, y_pos, x_inc, y_inc, course, warp);
      IF (ROUND (x_pos) IN [0..quad_size]) AND 
                                         (ROUND (y_pos) IN [0..quad_size]) THEN
        IF quadrant[ROUND (x_pos), ROUND (y_pos)] = s_fed_base THEN
          BEGIN
            WRITELN ('Collision with starbase''s elastic shields at sector ',
                     ROUND (x_pos), '-', ROUND (y_pos));
            move_intra (x_pos, y_pos, x_inc, y_inc, (course + 180) MOD 360, warp);
          END {of IF};
      IF (ROUND (x_pos) IN [0..quad_size]) AND 
                                         (ROUND (y_pos) IN [0..quad_size]) THEN
        BEGIN
          IF quadrant[ROUND (x_pos), ROUND (y_pos)] IN 
                                 [s_star, s_nova, s_klingon, s_kling_base] THEN
            BEGIN
              WRITELN ('Enterprise blocked by object at sector ', ROUND (x_pos),
                       '-', ROUND (y_pos));
              x_pos := x_pos - x_inc;
              y_pos := y_pos - y_inc;
            END {of IF quadrant};
          cur_sect.x := interval (ROUND (x_pos), 0, quad_size);
          cur_sect.y := interval (ROUND (y_pos), 0, quad_size);
          quadrant[cur_sect.x, cur_sect.y] := s_enterprise;
        END {of IF ROUND}
      ELSE
        BEGIN           {Inter-Quadrant moving}
          cur_quad.x := interval (TRUNC (cur_quad.x + warp * x_inc +
                                         cur_sect.x * 0.125), 0, galaxy_size);
          cur_quad.y := interval (TRUNC (cur_quad.y + warp * y_inc +
                                         cur_sect.y * 0.125), 0, galaxy_size);
          setup_quad (cur_quad, cur_sect);
        END {of IF};
    END {of ELSE};
  set_condition;
  IF condition = c_docked THEN
    re_initialize;
END {of move_enterprise};

PROCEDURE fire_phasers;
VAR i, fire_amount, hit : INTEGER;
BEGIN
  WRITELN ('Phasers locked on target.  Energy available = ', cur_energy);
  WRITE ('Number of units to fire: ');
  READLN (fire_amount);
  IF fire_amount > cur_energy THEN
    WRITELN ('Unable to fire.')
  ELSE
    IF fire_amount > 0 THEN
      BEGIN
        IF condition <> c_docked THEN
          cur_energy := cur_energy - fire_amount;
        FOR i := 0 TO max_klingons DO
          WITH klingons[i] DO
            IF energy_left > 0 THEN
              BEGIN
                hit := TRUNC (fire_amount /
                              distance (position.x, position.y, cur_sect) * 
                              (10 + random (0, 10))) DIV 10;
                energy_left := energy_left - hit;
                WRITE (hit, ' unit hit on Klingon at sector ', position.x, '-',
                       position.y);
                IF energy_left > 0 THEN
                  WRITELN (' (', energy_left, ' left)')
                ELSE
                  BEGIN
                    WRITELN ('.  Klingon DESTROYED', bell);
                    total_klingons := total_klingons - 1;
                    galaxy[cur_quad.x, cur_quad.y].kling_num := 
                                  galaxy[cur_quad.x, cur_quad.y].kling_num - 1;
                    quadrant[position.x, position.y] := s_nothing;
                  END {of ELSE};
              END {of IF energy_left}
      END {of IF >};
END {of fire_phasers};

PROCEDURE fire_torpedoes;
VAR i, course : INTEGER;
    hit_something : BOOLEAN;
    x_inc, y_inc, x_pos, y_pos : REAL;
                             
  PROCEDURE hit_nova (nova_x, nova_y : sect_range; VAR kling_num : INTEGER);
  VAR hit, i : INTEGER;
  BEGIN
    WRITELN ('Torpedo causes unstable star to nova');
    IF condition <> c_docked THEN
      BEGIN
        hit := 600 * random (0, 10) DIV distance (nova_x, nova_y, cur_sect);
        IF hit > 0 THEN
          WRITELN ('Enterprise loses ', hit, ' units of energy');
        cur_energy := cur_energy - hit;
      END {of IF};
    FOR i := 0 TO max_klingons DO
      WITH klingons[i] DO
        IF energy_left > 0 THEN
          BEGIN
            energy_left := energy_left - 120 * random (0, 10) DIV 
                             distance (nova_x, nova_y, position);
            IF energy_left <= 0 THEN
              BEGIN
                quadrant[position.x, position.y] := s_nothing;
                total_klingons := total_klingons - 1;
                kling_num := kling_num - 1;
              END {of IF <=};
          END {of IF >};
  END {of hit_nova};

  PROCEDURE hit_kling_base (VAR kling_base_num : INTEGER);
  VAR i, k_docked : INTEGER;
      quad_x, quad_y : quad_range;
  BEGIN 
    WRITELN ('*** Klingon Starbase DESTROYED ***', bell);
    kling_base_num := kling_base_num - 1;
    k_docked := 0;
    FOR i := 1 TO random (0, SQR (galaxy_size)) DO
      BEGIN
        REPEAT
          quad_x := random (0, galaxy_size);
          quad_y := random (0, galaxy_size);
        UNTIL (quad_x <> cur_quad.x) OR (quad_y <> cur_quad.y);
        k_docked := k_docked + galaxy[quad_x, quad_y].kling_num;
        galaxy[quad_x, quad_y].kling_num := 0;
      END {of FOR};
    WRITELN (k_docked, ' Klingons were killed while docked');
    total_klingons := total_klingons - k_docked;
  END {of hit_kling_base};

BEGIN {of fire_torpedoes}
  IF cur_torps = 0 THEN
    WRITELN ('All photon torpedoes expended.')
  ELSE
    BEGIN
      WRITE ('Torpedo course: ');
      READLN (course);
      IF condition <> c_docked THEN
        cur_torps := cur_torps - 1;
      x_inc := -COS (radians (course));
      y_inc := SIN (radians (course));
      x_pos := cur_sect.x;
      y_pos := cur_sect.y;
      hit_something := FALSE;
      WRITELN ('Torpedo track:');
      WITH galaxy[cur_quad.x, cur_quad.y] DO
        WHILE NOT hit_something AND (ROUND (x_pos) IN [0..quad_size]) AND
              (ROUND (y_pos) IN [0..quad_size]) DO
          CASE quadrant[ROUND (x_pos), ROUND (y_pos)] OF
            s_enterprise,
            s_nothing    : BEGIN
                             WRITELN (ROUND (x_pos), '-', ROUND (y_pos));
                             x_pos := x_pos + x_inc;
                             y_pos := y_pos + y_inc;
                           END {of s_nothing};
            s_star       : BEGIN
                             hit_something := TRUE;
                             WRITELN ('Star destroyed, you got the planets, ',
                                      'too!  Nice shot!');
                             bad_points := bad_points + random (0, 500);
                             star_num := star_num - 1;
                           END {of s_star};
            s_nova       : BEGIN
                             hit_something := TRUE;
                             star_num := star_num - 1;
                             hit_nova (ROUND (x_pos), ROUND (y_pos), kling_num);
                           END {of s_nova};
            s_klingon    : BEGIN
                             hit_something := TRUE;
                             WRITE ('*** Klingon DESTROYED ***', bell);
                             IF random (0, 100) < 30 THEN
                               WRITE (' (The only good Klingon is a dead',
                                      ' Klingon)');
                             WRITELN;
                             kling_num := kling_num - 1;
                             total_klingons := total_klingons - 1;
                             FOR i := 0 TO max_klingons DO
                               WITH klingons[i] DO
                                 IF (energy_left > 0) AND 
                                    (ROUND (x_pos) = position.x) AND 
                                    (ROUND (y_pos) = position.y) THEN
                                   energy_left := 0;
                           END {of s_klingon};
            s_fed_base   : BEGIN
                             hit_something := TRUE;
                             WRITELN ('*** Starbase destroyed ... ',
                                      'Congratulations ... Dummy ***');
                             bad_points := bad_points + random (0, 500);
                             fed_base_num := fed_base_num - 1;
                           END {of s_fed_base};
            s_kling_base : BEGIN
                             hit_something := TRUE;
                             hit_kling_base (kling_base_num);
                             total_k_bases := total_k_bases - 1;
                           END {of s_kling_base};
          END {of CASE};
      IF hit_something THEN
        quadrant[ROUND (x_pos), ROUND (y_pos)] := s_nothing
      ELSE
        WRITELN ('Torpedo missed.');
    END {of ELSE};
END {of fire_torpedoes};

PROCEDURE self_destruct;
VAR ch : CHAR;
BEGIN
  REPEAT
    WRITE ('Are you SURE ? ');
    READ (ch);
    WRITELN;
  UNTIL ch IN ['y', 'Y', 'n', 'N'];
  IF ch IN ['y', 'Y'] THEN
    EXIT (star_trek);
END {of self_destruct};

PROCEDURE command;
VAR ch : CHAR;
    valid_command : BOOLEAN;
BEGIN
  REPEAT
    WRITE ('Command: ');
    READLN (ch);
    WRITELN;
    valid_command := ch IN [min_device..max_device];
    IF valid_command THEN
      BEGIN
        IF (device[ch].down_time <> 0) AND (ch > SUCC (min_device)) THEN
          WRITELN ('*** ', device[ch].name, ' INOPERABLE ***')
        ELSE
          CASE ch OF 
            '0' : move_enterprise;
            '1' : print_quadrant;
            '2' : print_galaxy (cur_quad.x - 1, cur_quad.y - 1, 2, TRUE);
            '3' : fire_phasers;
            '4' : fire_torpedoes;
            '5' : print_damage;
            '6' : print_galaxy (0, 0, galaxy_size, FALSE);
            '7' : self_destruct;
          END {of CASE};
      END {of IF}
    ELSE
      BEGIN
        WRITELN ('0 = Set course');
        WRITELN ('1 = Short range sensor scan');
        WRITELN ('2 = Long range sensor scan');
        WRITELN ('3 = Fire phasors');
        WRITELN ('4 = Fire photon torpedoes');
        WRITELN ('5 = Damage control report');
        WRITELN ('6 = History computer report');
        WRITELN ('7 = Self destruct');
      END {of ELSE};
  UNTIL valid_command;
  IF ch IN ['0', '3', '4'] THEN
    BEGIN
      klingon_attack;
      print_quadrant;
    END {of IF};
END {of command};

                         {ending of STAR.PART2.TEXT}

